package com.google.code.opengw.server.domain;

import java.util.NoSuchElementException;

import com.google.code.opengw.support.OpenGWException;
import com.google.code.opengw.support.OpenGWLogger;



public class WorkerManager implements Runnable {

	private final Domain domain;
	private final WorkerPool workerPool;
	private boolean systemActive;
	private boolean managerAlive;
	
	public WorkerManager(Domain domain, WorkerPool workerPool) {
		this.domain = domain;
		this.workerPool = workerPool;
		systemActive = true;
		managerAlive = false;
		try{
			while(true){
				Worker worker = new Worker(domain,this);
				workerPool.addWorker(worker);
				Thread workerThread = new Thread(worker);
				workerThread.start();
			}
		} catch (OpenGWException e) {
		}
	}
	
	@Override
	public void run() {
		managerAlive = true;
		try{
			while (systemActive) {
				try{
					if(workerPool.isAvaliableConnection() && workerPool.isAvaliableWorker()){
						Worker worker = workerPool.getWorker();
						worker.activate();
					} else if(!workerPool.isAvaliableConnection()){
						try{
							Thread.sleep(10);
						} catch (Exception ex) {
						}
					} else if(workerPool.isPoolSizeIncrementNeed()){
						int increaseCount = workerPool.increasePoolSize();
						try{
							for(int i=0;i<increaseCount;i++){
								Worker worker = new Worker(domain,this);
								workerPool.addWorker(worker);
								Thread workerThread = new Thread(worker);
								workerThread.start();
							}
							OpenGWLogger.addInfo(this.getClass(), "worker size increased " +  " now : " + workerPool.getPoolSize());
						} catch (OpenGWException e2) {
							OpenGWLogger.addError(this.getClass(), e2.getMessage(), e2);
						}
						
					}
				} catch (NoSuchElementException e) {
					try{
						Thread.sleep(10);
					} catch (Exception ex) {
					}
				}
			}
		} catch (Exception e) {
			OpenGWLogger.addError(this.getClass(), e.getMessage(), e);
		} finally {
			managerAlive = false;
		}
		
	}
	
	
	public boolean isManagerAlive(){
		return managerAlive;
	}
	
	public void setSystemActive(boolean systemActive) {
		this.systemActive = systemActive;
	}

	public synchronized void changeWorkerState(Worker worker){
		workerPool.avaliableWorker(worker);
	}

}
